From: Keir Fraser Date: Wed, 20 Oct 2010 15:36:32 +0000 (+0100) Subject: hvmloader: Properly block on xenstore daemon rather than merely yielding. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~11376 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks:///%22http:/www.example.com/cgi/%22https:/%22bookmarks:/?a=commitdiff_plain;h=da7abb1417a92981a356abcb3a8fa85c97dfff31;p=xen.git hvmloader: Properly block on xenstore daemon rather than merely yielding. Signed-off-by: Keir Fraser --- diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index 3c661360b2..e2d7e01e96 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -35,6 +35,16 @@ static inline int test_bit(unsigned int b, void *p) return !!(((uint8_t *)p)[b>>3] & (1u<<(b&7))); } +static inline int test_and_clear_bit(int nr, volatile void *addr) +{ + int oldbit; + asm volatile ( + "lock ; btrl %2,%1 ; sbbl %0,%0" + : "=r" (oldbit), "=m" (*(volatile long *)addr) + : "Ir" (nr), "m" (*(volatile long *)addr) : "memory"); + return oldbit; +} + /* MSR access */ void wrmsr(uint32_t idx, uint64_t v); uint64_t rdmsr(uint32_t idx); diff --git a/tools/firmware/hvmloader/xenbus.c b/tools/firmware/hvmloader/xenbus.c index 12d67b38e7..90245f57b1 100644 --- a/tools/firmware/hvmloader/xenbus.c +++ b/tools/firmware/hvmloader/xenbus.c @@ -25,9 +25,9 @@ #include #include -struct xenstore_domain_interface *rings; /* Shared ring with dom0 */ -evtchn_port_t event; /* Event-channel to dom0 */ -char payload[XENSTORE_PAYLOAD_MAX + 1]; /* Unmarshalling area */ +static struct xenstore_domain_interface *rings; /* Shared ring with dom0 */ +static evtchn_port_t event; /* Event-channel to dom0 */ +static char payload[XENSTORE_PAYLOAD_MAX + 1]; /* Unmarshalling area */ /* Connect our xenbus client to the backend. * Call once, before any other xenbus actions. */ @@ -69,6 +69,19 @@ void xenbus_shutdown(void) rings = NULL; } +static void ring_wait(void) +{ + struct shared_info *shinfo = get_shared_info(); + struct sched_poll poll; + + memset(&poll, 0, sizeof(poll)); + set_xen_guest_handle(poll.ports, &event); + poll.nr_ports = 1; + + while ( !test_and_clear_bit(event, shinfo->evtchn_pending) ) + hypercall_sched_op(SCHEDOP_poll, &poll); +} + /* Helper functions: copy data in and out of the ring */ static void ring_write(char *data, uint32_t len) { @@ -79,8 +92,9 @@ static void ring_write(char *data, uint32_t len) while ( len ) { /* Don't overrun the consumer pointer */ - part = (XENSTORE_RING_SIZE - 1) - - MASK_XENSTORE_IDX(rings->req_prod - rings->req_cons); + while ( (part = (XENSTORE_RING_SIZE - 1) - + MASK_XENSTORE_IDX(rings->req_prod - rings->req_cons)) == 0 ) + ring_wait(); /* Don't overrun the end of the ring */ if ( part > (XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->req_prod)) ) part = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->req_prod); @@ -92,9 +106,6 @@ static void ring_write(char *data, uint32_t len) barrier(); /* = wmb before prod write, rmb before next cons read */ rings->req_prod += part; len -= part; - - if ( len ) - hypercall_sched_op(SCHEDOP_yield, NULL); } } @@ -107,7 +118,9 @@ static void ring_read(char *data, uint32_t len) while ( len ) { /* Don't overrun the producer pointer */ - part = MASK_XENSTORE_IDX(rings->rsp_prod - rings->rsp_cons); + while ( (part = MASK_XENSTORE_IDX(rings->rsp_prod - + rings->rsp_cons)) == 0 ) + ring_wait(); /* Don't overrun the end of the ring */ if ( part > (XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->rsp_cons)) ) part = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->rsp_cons); @@ -119,9 +132,6 @@ static void ring_read(char *data, uint32_t len) barrier(); /* = wmb before cons write, rmb before next prod read */ rings->rsp_cons += part; len -= part; - - if ( len ) - hypercall_sched_op(SCHEDOP_yield, NULL); } }